open Base
open Math

type event =
  | Click of Pos.t
and t = event

let equal (Click p1) (Click p2) = Pos.equal p1 p2
let to_string = function
  | Click p -> Printf.sprintf "Click(%s)" (Pos.to_string p)


type handler =
  event -> (Source.value -> Source.value) Source.map

let handler_compose (f : handler) (g : handler) : handler =
  fun ev ->
  Map.merge_skewed (f ev) (g ev)
    ~combine:(fun ~key:_ f' g' x -> f' (g' x))


module Id : sig
  include Identifiable.S
  val gen : unit -> t
  module Private : sig
    val next_id : diff:int -> t
  end
end = struct
  include (Int : Identifiable.S with type t = int)
  let next = ref 0
  let gen () = let v = !next in Int.incr next ; v
  let to_string v = Printf.sprintf "<id:%d>" v
  module Private = struct
    let next_id ~diff = !next + diff
  end
end

type 'a map = (Id.t, 'a, Id.comparator_witness) Map.t
let empty_map : _ map = Map.empty (module Id)
